package org.example.exampreparationtreasure.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.example.exampreparationtreasure.mapper.*;
import org.example.exampreparationtreasure.model.entity.*;
import org.example.exampreparationtreasure.service.PracticeModeService;
import org.example.exampreparationtreasure.service.IncorrectQuestionRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class PracticeModeServiceImpl implements PracticeModeService {

    @Autowired
    private ChapterQuestionSelectorServiceImpl chapterService;

    @Autowired
    private RandomQuestionSelectorServiceImpl randomService;

    @Autowired
    private SpecializedQuestionSelectorServiceImpl specializedService;

    @Autowired
    private MockExamQuestionSelectorServiceImpl mockExamService;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private AnswerMapper answerMapper;

    @Autowired
    private ExamPaperMapper examPaperMapper;

    @Autowired
    private ExamPaperQuestionMapper examPaperQuestionMapper;

    @Autowired
    private ExamConfigurationMapper examConfigurationMapper;

    @Autowired
    private ExamRecordMapper examRecordMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private IncorrectQuestionRecordService incorrectQuestionRecordService;

    @Override
    public List<Question> selectQuestions(ExamPaperConfig config, Long userId) {
        PracticeMode mode = config.getMode();

        switch (mode) {
            case CHAPTER:
                return chapterService.selectQuestions(config, userId);
            case RANDOM:
                return randomService.selectQuestions(config, userId);
            case SPECIALIZED:
                return specializedService.selectQuestions(config, userId);
            case MOCK_EXAM:
                return mockExamService.selectQuestions(config, userId);
            default:
                throw new IllegalArgumentException("不支持的练习模式: " + mode);
        }
    }

    @Override
    @Transactional
    public Long startExam(ExamPaperConfig config, Long userId, List<Question> questions) {
        return savePaperAndStartExam(config, userId, questions);
    }

    /**
     * 保存完整试卷数据并开始考试
     */
    @Transactional
    public Long savePaperAndStartExam(ExamPaperConfig config, Long userId, List<Question> questions) {
        // 1. 保存试卷配置到 exam_configurations 表
        ExamConfiguration examConfig = new ExamConfiguration();
        examConfig.setConfigName(generateConfigName(config));
        examConfig.setGenerationMode(getModeText(config.getMode()));
        examConfig.setTimeLimit(config.getTimeLimitMinutes());
        examConfig.setInitialDifficulty(getDifficultyText(config.getInitialDifficulty()));
        examConfig.setCreatorId(userId);
        examConfig.setCreateTime(LocalDateTime.now());
        examConfig.setUpdateTime(LocalDateTime.now());
        examConfigurationMapper.insert(examConfig);
        
        // 2. 保存试卷到 exam_papers 表
        ExamPaper examPaper = new ExamPaper();
        examPaper.setPaperTitle(generateExamTitle(config, questions.size()));
        examPaper.setGenerationTime(LocalDateTime.now());
        examPaper.setGeneratorId(userId);
        examPaper.setConfigId(examConfig.getConfigId());
        examPaper.setCreateTime(LocalDateTime.now());
        examPaper.setUpdateTime(LocalDateTime.now());
        examPaperMapper.insert(examPaper);
        
        // 3. 保存试卷题目关联到 exam_paper_questions 表
        List<ExamPaperQuestion> paperQuestions = new ArrayList<>();
        BigDecimal defaultScore = calculateDefaultScore(questions.size());
        
        for (int i = 0; i < questions.size(); i++) {
            ExamPaperQuestion epq = new ExamPaperQuestion();
            epq.setPaperId(examPaper.getPaperId());
            epq.setQuestionId(questions.get(i).getQuestionId());
            epq.setQuestionOrder(i + 1);
            epq.setQuestionScore(defaultScore);
            epq.setCreateTime(LocalDateTime.now());
            epq.setUpdateTime(LocalDateTime.now());
            paperQuestions.add(epq);
        }
        examPaperQuestionMapper.insertBatch(paperQuestions);
        
        // 4. 创建考试记录到 exam_record 表
        ExamRecord examRecord = new ExamRecord();
        examRecord.setExamRecordId(generateExamRecordId());
        examRecord.setUserId(userId);
        examRecord.setPaperId(examPaper.getPaperId());
        examRecord.setConfigId(examConfig.getConfigId());
        examRecord.setStartTime(LocalDateTime.now());
        examRecord.setTotalQuestions(questions.size());
        examRecord.setExamineeId(userId); // 设置考生ID，通常与用户ID相同
        examRecord.setStatus("进行中");
        examRecord.setPracticeMode(config.getMode().name());
        examRecord.setCreateTime(LocalDateTime.now());
        examRecord.setUpdateTime(LocalDateTime.now());
        examRecordMapper.insert(examRecord);
        
        return examRecord.getExamRecordId();
    }

    @Override
    @Transactional
    public Map<String, Object> submitExam(Long examRecordId, Long userId, List<Map<String, Object>> answersData, Integer examDuration) {
        System.out.println("=== 开始提交考试 ===");
        System.out.println("examRecordId: " + examRecordId);
        System.out.println("userId: " + userId);
        
        // 从数据库查询现有的考试记录
        ExamRecord examRecord = examRecordMapper.selectById(examRecordId);
        if (examRecord == null) {
            throw new RuntimeException("考试记录不存在，ID: " + examRecordId);
        }
        
        if (!examRecord.getUserId().equals(userId)) {
            throw new RuntimeException("无权限访问此考试记录");
        }
        
        // 检查考试是否已经提交过
        if ("已完成".equals(examRecord.getStatus())) {
            throw new RuntimeException("考试已经提交过，不能重复提交");
        }
        
        System.out.println("查询到的考试记录: " + examRecord);
        
        // 检查是否已存在答案记录，如果存在则先删除（防止重复提交）
        QueryWrapper<Answer> existingAnswerWrapper = new QueryWrapper<>();
        existingAnswerWrapper.eq("exam_record_id", examRecordId);
        List<Answer> existingAnswers = answerMapper.selectList(existingAnswerWrapper);
        if (!existingAnswers.isEmpty()) {
            System.out.println("发现已存在的答案记录，先删除: " + existingAnswers.size() + " 条");
            answerMapper.delete(existingAnswerWrapper);
        }
        
        // 更新考试结束信息
        examRecord.setEndTime(LocalDateTime.now());
        examRecord.setExamDuration(examDuration);

        // 去重处理：使用 Set 来避免重复的题目ID
        Set<Long> processedQuestionIds = new HashSet<>();
        List<Answer> answers = new ArrayList<>();
        int correctCount = 0;
        double totalScore = 0.0;

        for (Map<String, Object> answerData : answersData) {
            Long questionId = Long.valueOf(answerData.get("questionId").toString());
            
            // 检查是否已经处理过这道题
            if (processedQuestionIds.contains(questionId)) {
                System.out.println("跳过重复的题目ID: " + questionId);
                continue;
            }
            processedQuestionIds.add(questionId);
            
            Map<String, Object> userAnswer = (Map<String, Object>) answerData.get("userAnswer");

            // 获取题目信息
            Question question = questionMapper.selectById(questionId);
            if (question == null) {
                System.out.println("题目不存在，跳过: " + questionId);
                continue;
            }

            // 判断答案是否正确
            Boolean isCorrect = judgeAnswer(question, userAnswer);
            if (isCorrect) {
                correctCount++;
            }

            // 计算得分
            Double score = calculateScore(question, isCorrect);
            totalScore += score;

            // 创建答案记录
            Answer answer = new Answer();
            answer.setExamRecordId(examRecordId);
            answer.setQuestionId(questionId);
            answer.setUserAnswer(userAnswer);
            answer.setQuestionScore(BigDecimal.valueOf(score));
            //answer.setIsCorrect(isCorrect);
            answer.setIsCorrect(isCorrect ? 1:0);

            answer.setUserId(userId);
            answer.setCreateTime(LocalDateTime.now());
            answer.setUpdateTime(LocalDateTime.now());

            answers.add(answer);
        }
        
        // 批量插入答案记录
        if (!answers.isEmpty()) {
            for (Answer answer : answers) {
                try {
                    answerMapper.insert(answer);
                } catch (Exception e) {
                    System.err.println("插入答案记录失败: " + e.getMessage());
                    throw new RuntimeException("保存答案失败: " + e.getMessage());
                }
            }
        }

        // 自动记录错题
        for (Answer answer : answers) {
            if (answer.getIsCorrect() == 0) {
                incorrectQuestionRecordService.addIncorrectQuestion(userId, answer.getQuestionId(), null);
            }
        }

        // 更新考试记录
        int totalQuestions = answers.size();
        int incorrectCount = totalQuestions - correctCount;
        double accuracy = totalQuestions > 0 ? (double) correctCount / totalQuestions * 100 : 0;

        examRecord.setCorrectAnswers(correctCount);
        examRecord.setIncorrectAnswers(incorrectCount);
        examRecord.setTotalScore(BigDecimal.valueOf(totalScore));
        examRecord.setAccuracy(BigDecimal.valueOf(accuracy));
        examRecord.setStatus("已完成");
        examRecord.setUpdateTime(LocalDateTime.now());
        examRecordMapper.updateById(examRecord);

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("examRecordId", examRecordId);
        result.put("examTitle", generateExamTitleFromMode(examRecord.getPracticeMode(), totalQuestions)); // 修复：直接生成考试标题
        result.put("examMode", examRecord.getPracticeMode());
        result.put("startTime", examRecord.getStartTime());
        result.put("endTime", examRecord.getEndTime());
        result.put("examDuration", examDuration);
        result.put("totalQuestions", totalQuestions);
        result.put("correctAnswers", correctCount);
        result.put("incorrectAnswers", incorrectCount);
        result.put("accuracy", accuracy);
        result.put("totalScore", totalScore);
        result.put("answers", answers);
        result.put("status", "已完成");

        return result;
    }

    @Override
    public Boolean judgeAnswer(Question question, Map<String, Object> userAnswer) {
        String questionType = question.getQuestionType();
        Map<String, Object> questionContent = question.getQuestionContent();

        switch (questionType) {
            case "single_choice":
            case "单选":
            case "单选题":
                return judgeSingleChoice(questionContent, userAnswer);
            case "multiple_choice":
            case "多选":
            case "多选题":
                return judgeMultipleChoice(questionContent, userAnswer);
            case "true_false":
            case "判断":
            case "判断题":
                return judgeTrueFalse(questionContent, userAnswer);
            case "fill_blank":
            case "填空":
            case "填空题":
                return judgeFillBlank(questionContent, userAnswer);
            case "short_answer":
            case "简答":
            case "简答题":
                return judgeShortAnswer(questionContent, userAnswer);
            default:
                throw new IllegalArgumentException("不支持的题型: " + questionType + "。支持的题型: single_choice, multiple_choice, fill_blank, short_answer");
        }
    }


    @Override
    public Double calculateScore(Question question, Boolean isCorrect) {
        if (!isCorrect) {
            return 0.0;
        }

        // 根据题目难度计算分数
        String difficulty = question.getDifficulty();
        switch (difficulty) {
            case "easy":
            case "简单":
            case "易":
                return 10.0;
            case "medium":
            case "中等":
            case "中":
                return 15.0;
            case "hard":
            case "困难":
            case "难":
                return 20.0;
            default:
                System.out.println("未知难度: " + difficulty + ", 使用默认分值");
                return 10.0;
        }
    }

    /**
     * 生成配置名称
     */
    private String generateConfigName(ExamPaperConfig config) {
        String modeText = getModeText(config.getMode());
        String categoryText = getCategoryText(config.getCategoryId());
        return String.format("%s-%s配置", categoryText, modeText);
    }

    /**
     * 生成考试标题
     */
    private String generateExamTitle(ExamPaperConfig config, int totalQuestions) {
        String modeText = getModeText(config.getMode());
        String categoryText = getCategoryText(config.getCategoryId());
        return String.format("%s-%s - %d题", categoryText, modeText, totalQuestions);
    }

    /**
     * 根据练习模式生成考试标题
     */
    private String generateExamTitleFromMode(String practiceMode, Integer totalQuestions) {
        try {
            String modeText = getModeTextFromString(practiceMode);
            int questionCount = totalQuestions != null ? totalQuestions : 0;
            return String.format("%s练习 - %d题", modeText, questionCount);
        } catch (Exception e) {
            System.err.println("生成考试标题时出错: " + e.getMessage());
            return "练习 - 0题";
        }
    }

    /**
     * 从字符串获取模式文本
     */
    private String getModeTextFromString(String practiceMode) {
        if (practiceMode == null || practiceMode.trim().isEmpty()) {
            return "练习";
        }
        
        try {
            switch (practiceMode.trim().toUpperCase()) {
                case "CHAPTER": return "章节";
                case "RANDOM": return "随机";
                case "SPECIALIZED": return "专项";
                case "MOCK_EXAM": return "模拟";
                default: 
                    System.out.println("未知的练习模式: " + practiceMode + ", 使用默认值");
                    return "练习";
            }
        } catch (Exception e) {
            System.err.println("解析练习模式时出错: " + e.getMessage());
            return "练习";
        }
    }



    /**
     * 获取模式文本
     */
    private String getModeText(PracticeMode mode) {
        switch (mode) {
            case CHAPTER: return "章节";
            case RANDOM: return "随机";
            case SPECIALIZED: return "专项";
            case MOCK_EXAM: return "模拟";
            default: return "练习";
        }
    }

    /**
     * 获取难度文本
     */
    private String getDifficultyText(Integer difficulty) {
        switch (difficulty) {
            case 1: return "易";
            case 2: return "中";
            case 3: return "难";
            default: return "易";
        }
    }

    /**
     * 获取分类文本
     */
    private String getCategoryText(Long categoryId) {
        if (categoryId == null) {
            return "全部";
        }
        try {
            Categories category = categoryMapper.selectById(categoryId);
            return category != null ? category.getCategoryName() : "未知分类";
        } catch (Exception e) {
            return "未知分类";
        }
    }

    /**
     * 计算默认分值
     */
    private BigDecimal calculateDefaultScore(int questionCount) {
        // 总分100分，平均分配
        return BigDecimal.valueOf(100.0 / questionCount).setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 生成考试记录ID
     */
    private Long generateExamRecordId() {
        // 使用时间戳生成唯一ID
        return System.currentTimeMillis();
    }

    @Override
    public Map<String, Object> getExamResult(Long examRecordId, Long userId) {
        System.out.println("=== Service层开始处理 ===");
        System.out.println("examRecordId: " + examRecordId);
        System.out.println("userId: " + userId);
        
        try {
            // 1. 检查 mapper 是否为空
            if (examRecordMapper == null) {
                System.err.println("examRecordMapper 为 null!");
                throw new RuntimeException("数据访问层未初始化");
            }
            
            System.out.println("开始查询考试记录...");
            
            // 2. 查询考试记录
            ExamRecord examRecord = examRecordMapper.selectById(examRecordId);
            System.out.println("查询结果: " + examRecord);
            
            if (examRecord == null) {
                System.out.println("考试记录不存在: " + examRecordId);
                throw new RuntimeException("考试记录不存在，ID: " + examRecordId);
            }
            
            System.out.println("考试记录存在，检查用户权限...");
            System.out.println("记录中的用户ID: " + examRecord.getUserId());
            System.out.println("请求的用户ID: " + userId);
            
            if (!examRecord.getUserId().equals(userId)) {
                throw new RuntimeException("无权限访问此考试记录");
            }

            System.out.println("权限检查通过，开始查询答题记录...");

            // 3. 查询答题记录
            if (answerMapper == null) {
                System.err.println("answerMapper 为 null!");
                throw new RuntimeException("答题记录访问层未初始化");
            }
            
            QueryWrapper<Answer> answerWrapper = new QueryWrapper<>();
            answerWrapper.eq("exam_record_id", examRecordId);
            List<Answer> answers = answerMapper.selectList(answerWrapper);
            System.out.println("答题记录数量: " + (answers != null ? answers.size() : 0));

            System.out.println("开始构建返回结果...");

            // 4. 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("examRecordId", examRecordId);
            result.put("examTitle", "测试考试");  // 先用固定值避免方法调用问题
            result.put("examMode", examRecord.getPracticeMode());
            result.put("startTime", examRecord.getStartTime());
            result.put("endTime", examRecord.getEndTime());
            result.put("totalQuestions", examRecord.getTotalQuestions());
            result.put("status", examRecord.getStatus());
            result.put("answers", answers != null ? answers : new ArrayList<>());

            System.out.println("结果构建完成，返回数据");
            return result;
            
        } catch (Exception e) {
            System.err.println("=== Service层发生错误 ===");
            System.err.println("错误类型: " + e.getClass().getSimpleName());
            System.err.println("错误信息: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("获取考试结果失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Map<String, Object> getExamHistory(Long userId, Integer page, Integer size, String practiceMode) {
        // 构建查询条件
        QueryWrapper<ExamRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        if (practiceMode != null && !practiceMode.isEmpty()) {
            queryWrapper.eq("practice_mode", practiceMode);
        }
        queryWrapper.orderByDesc("create_time");

        // 分页查询
        Page<ExamRecord> pageObj = new Page<>(page, size);
        IPage<ExamRecord> examRecords = examRecordMapper.selectPage(pageObj, queryWrapper);

        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("records", examRecords.getRecords());
        result.put("total", examRecords.getTotal());
        result.put("pages", examRecords.getPages());
        result.put("current", examRecords.getCurrent());
        result.put("size", examRecords.getSize());

        return result;
    }

    private Boolean judgeSingleChoice(Map<String, Object> questionContent, Map<String, Object> userAnswer) {
        // 支持多种答案字段名称
        String correctAnswer = (String) questionContent.get("answer");
        if (correctAnswer == null) {
            correctAnswer = (String) questionContent.get("correctAnswer");
        }
        
        String userChoice = (String) userAnswer.get("selectedOption");
        
        // 添加调试日志
        System.out.println("题目内容: " + questionContent);
        System.out.println("正确答案: " + correctAnswer);
        System.out.println("用户选择: " + userChoice);
        
        return correctAnswer != null && correctAnswer.equals(userChoice);
    }

    private Boolean judgeMultipleChoice(Map<String, Object> questionContent, Map<String, Object> userAnswer) {
        @SuppressWarnings("unchecked")
        List<String> correctAnswers = (List<String>) questionContent.get("correctAnswers");
        @SuppressWarnings("unchecked")
        List<String> userChoices = (List<String>) userAnswer.get("selectedOptions");

        if (correctAnswers == null || userChoices == null) {
            return false;
        }

        if (correctAnswers.size() != userChoices.size()) {
            return false;
        }

        Collections.sort(correctAnswers);
        Collections.sort(userChoices);
        return correctAnswers.equals(userChoices);
    }

    private Boolean judgeTrueFalse(Map<String, Object> questionContent, Map<String, Object> userAnswer) {
        Boolean correctAnswer = (Boolean) questionContent.get("correctAnswer");
        Boolean userChoice = (Boolean) userAnswer.get("selectedOption");
        return correctAnswer != null && correctAnswer.equals(userChoice);
    }

    private Boolean judgeFillBlank(Map<String, Object> questionContent, Map<String, Object> userAnswer) {
        @SuppressWarnings("unchecked")
        List<String> correctAnswers = (List<String>) questionContent.get("correctAnswers");
        @SuppressWarnings("unchecked")
        List<String> userAnswers = (List<String>) userAnswer.get("answers");

        if (correctAnswers == null || userAnswers == null) {
            return false;
        }

        if (correctAnswers.size() != userAnswers.size()) {
            return false;
        }

        // 填空题允许模糊匹配（忽略大小写和空格）
        for (int i = 0; i < correctAnswers.size(); i++) {
            String correct = correctAnswers.get(i).trim().toLowerCase();
            String user = userAnswers.get(i).trim().toLowerCase();
            if (!correct.equals(user)) {
                return false;
            }
        }
        return true;
    }

    private Boolean judgeShortAnswer(Map<String, Object> questionContent, Map<String, Object> userAnswer) {
        @SuppressWarnings("unchecked")
        List<String> keywords = (List<String>) questionContent.get("keywords");
        String userText = (String) userAnswer.get("answer");

        if (keywords == null || userText == null) {
            return false;
        }

        String lowerUserText = userText.toLowerCase();
        int matchedKeywords = 0;

        for (String keyword : keywords) {
            if (lowerUserText.contains(keyword.toLowerCase())) {
                matchedKeywords++;
            }
        }

        // 如果匹配的关键词超过一半，认为答案正确
        return matchedKeywords >= keywords.size() / 2.0;
    }
}

